package service

import (
	"awesomeProject/app/model"
	"awesomeProject/app/request"
	"awesomeProject/app/response"
	"awesomeProject/global"
	"context"
	"errors"
	"fmt"
	"github.com/fatih/structs"
)

type HostSrv struct{}

var accountSrv AccountSrv

func (r *HostSrv) Pagination(req request.HostPagination) response.Resp {
	offset := (req.PageIndex - 1) * req.PageSize
	where := "1=1"
	if req.Keyword != "" {
		where += " and (`host_ip` like '%" + req.Keyword +
			"%' or `host_username` like '%" + req.Keyword +
			"%' or `host_port` like '%" + req.Keyword + "%')"
	}
	if req.AccountUsername != "" {
		where += " and (`account_username` like '%" + req.AccountUsername + "%')"
	}
	var hosts []model.Host
	err := global.Gorm.Where(where).Offset(offset).Limit(req.PageSize).Find(&hosts).Error
	if err != nil {
		return response.ErrQuery
	}
	if len(hosts) == 0 {
		return response.OK.WithData(map[string]interface{}{
			"total": 0,
			"list":  hosts,
		})
	}

	var total int64
	err = global.Gorm.Model(&model.Host{}).Where(where).Count(&total).Error
	if err != nil {
		return response.ErrQuery
	}

	return response.OK.WithData(map[string]interface{}{
		"total": total,
		"list":  hosts,
	})
}

func (r *HostSrv) FindByID(id uint) (error, model.Host) {
	var host model.Host
	where := "1=1"
	err := global.Gorm.Where("id = ?", id).Where(where).First(&host).Error

	return err, host
}

func (r *HostSrv) FindByHostIp(hostIp string) (error, model.Host) {
	var host model.Host
	where := "1=1"
	err := global.Gorm.Where("host_ip = ?", hostIp).Where(where).First(&host).Error

	return err, host
}

func (r *HostSrv) FindByHostAccountUsername(hostAccountUsername string) (error, model.Host) {
	var host model.Host
	where := "1=1"
	err := global.Gorm.Where("account_username = ?", hostAccountUsername).Where(where).First(&host).Error

	return err, host
}

func (r *HostSrv) CheckHostIpExists(hostIp string, id uint) (bool) {
	var total int64
	err := global.Gorm.Model(&model.Host{}).Where("host_ip = ? and id != ?", hostIp, id).Count(&total).Error
	var check bool
	if err == nil {
		check = total > 0
	}
	return check
}

func (r *HostSrv) CheckAccountUsernameBind(accountUsername string, id uint) (bool) {
	var total int64
	err := global.Gorm.Model(&model.Host{}).Where("account_username = ? and id != ?", accountUsername, id).Count(&total).Error
	var check bool
	if err == nil {
		check = total > 0
	}
	return check
}

func (r *HostSrv) Update(id uint, req request.HostUpdate) response.Resp {
	err, host := r.FindByID(id)
	if err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}
	if host.ID == 0 {
		return response.ErrRecordNotFound
	}
	updates := structs.Map(req)
	if err = global.Gorm.Model(&host).Updates(updates).Error; err != nil {
		return response.ErrStore.SetMsg(err.Error())
	}
	// 更新关联店铺账号的密码信息
	if req.AccountUsername != "" && req.AccountPassword != "" && req.AccountOriginPwd != "" {
		accountPasswordFillAble := model.AccountPasswordFillAble{
			Username: req.AccountUsername,
			Password: req.AccountPassword,
			OriginPwd: req.AccountOriginPwd,
		}
		accountSrv.UpdatePassword(req.AccountUsername, accountPasswordFillAble)
	}
	// 更新相同相同IP记录的主机信息
	hostHostFillAble := model.HostHostFillAble{
		HostIP: req.HostIP,
		HostPort: req.HostPort,
		HostUsername: req.HostUsername,
		HostPassword: req.HostPassword,
		HostState: req.HostState,
	}
	r.UpdateHostHost(host.HostIP, hostHostFillAble)
	return response.OK
}

func (r *HostSrv) Create(hostFillAble model.HostFillAble, hostAccountFillAble model.HostAccountFillAble) response.Resp {
	hostObj := model.Host{
		HostFillAble: hostFillAble,
		HostAccountFillAble: hostAccountFillAble,
	}
	if err := global.Gorm.Model(&model.Host{}).Create(&hostObj).Error; err != nil {
		return response.ErrCreate.SetMsg(err.Error())
	}
	// 更新关联店铺账号的密码信息
	if hostAccountFillAble.AccountUsername != "" && hostAccountFillAble.AccountPassword != "" && hostAccountFillAble.AccountOriginPwd != "" {
		accountPasswordFillAble := model.AccountPasswordFillAble{
			Username: hostAccountFillAble.AccountUsername,
			Password: hostAccountFillAble.AccountPassword,
			OriginPwd: hostAccountFillAble.AccountOriginPwd,
		}
		accountSrv.UpdatePassword(hostAccountFillAble.AccountUsername, accountPasswordFillAble)
	}
	// 更新相同相同IP记录的主机信息
	hostHostFillAble := model.HostHostFillAble{
		HostIP: hostFillAble.HostIP,
		HostPort: hostFillAble.HostPort,
		HostUsername: hostFillAble.HostUsername,
		HostPassword: hostFillAble.HostPassword,
		HostState: hostFillAble.HostState,
	}
	r.UpdateHostHost(hostFillAble.HostIP, hostHostFillAble)
	return response.OK
}

func (r *HostSrv) UpdateHostHost(hostIp string, hostHostFillAble model.HostHostFillAble) response.Resp {
	updates := structs.Map(hostHostFillAble)
	if err := global.Gorm.Model(&model.Host{}).Where("host_ip = ?", hostIp).Updates(updates).Error; err != nil {
		return response.ErrStore.SetMsg(err.Error())
	}
	return response.OK
}

func (r *HostSrv) CreateHostByAccount(hostAccountFillAble model.HostAccountFillAble) response.Resp {
	hostObj := model.Host{
		HostAccountFillAble: hostAccountFillAble,
	}
	if err := global.Gorm.Model(&model.Host{}).Create(&hostObj).Error; err != nil {
		return response.ErrCreate.SetMsg(err.Error())
	}
	return response.OK
}

func (r *HostSrv) Del(id uint) response.Resp {
	err, host := r.FindByID(id)
	if err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}
	if host.ID == 0 {
		return response.ErrRecordNotFound
	}
	// 数据删除
	if err := global.Gorm.Unscoped().Delete(&host).Error; err != nil {
		return response.ErrDel.SetMsg(err.Error())
	}
	return response.OK
}

func (r *HostSrv) UpdateHostAccountPassword(hostAccountUsername string, hostAccountFillAble model.HostAccountFillAble) response.Resp {
	err, host := r.FindByHostAccountUsername(hostAccountUsername)
	if err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}
	if host.ID == 0 {
		return response.ErrRecordNotFound
	}
	updates := structs.Map(hostAccountFillAble)
	if err = global.Gorm.Model(&host).Updates(updates).Error; err != nil {
		return response.ErrStore.SetMsg(err.Error())
	}
	return response.OK
}

func (r *HostSrv) GetHostAccountByAccountUsername(accountUsername string) (error, model.Account){
	err, account := accountSrv.FindByUsername(accountUsername)
	return err, account
}

func (r *HostSrv) GetHostAccountByHostId(hostIp string) (error, model.Account) {
	var account model.Account
	err, host := r.FindByHostIp(hostIp)
	if err != nil {
		return errors.New("账户记录不存在"), account
	}
	if host.ID == 0 {
		return err, account
	}
	err, account = accountSrv.FindByUsername(host.AccountUsername)
	return err, account
}

func (r *HostSrv) HostStatesPagination(req request.HostStatesPagination) response.Resp {
	hostIp := req.HostIP
	accountUsername := req.AccountUsername
	offset := (req.PageIndex - 1) * req.PageSize
	where := "1=1"
	if req.Keyword != "" {
		where += " and (`state_flag` like '%" + req.Keyword +
			"%' or `flag_note` like '%" + req.Keyword +
			"%' or `value_note` like '%" + req.Keyword +
			"%' or `state_value` like '%" + req.Keyword + "%')"
	}
	if accountUsername != "" {
		err, host := hostSrv.FindByHostAccountUsername(accountUsername)
		if err != nil || host.ID == 0{
			where += " and (1=2)"
		}
		hostIp = host.HostIP
		where += " and (`host_ip`='" + hostIp + "' and (`account_username`='" + accountUsername + "' or `account_username`='@'))"
	} else {
		where += " and (`host_ip`='" + hostIp + "')"
	}
	var hostsStates []model.HostsStates
	err := global.Gorm.Where(where).Offset(offset).Limit(req.PageSize).Find(&hostsStates).Error
	if err != nil {
		return response.ErrQuery
	}
	if len(hostsStates) == 0 {
		return response.OK.WithData(map[string]interface{}{
			"total": 0,
			"list":  hostsStates,
		})
	}

	var total int64
	err = global.Gorm.Model(&model.HostsStates{}).Where(where).Count(&total).Error
	if err != nil {
		return response.ErrQuery
	}

	return response.OK.WithData(map[string]interface{}{
		"total": total,
		"list":  hostsStates,
	})
}

// 重启主机
func (r *HostSrv) HostReboot(req request.HostReboot) response.Resp {
	if req.HostIP != "" {
		// 给redis发布频道消息指令（每一个主机IP单独绑定一个频道）
		channelName := fmt.Sprintf("channel_for_host:%s", req.HostIP)
		channelMessge := fmt.Sprintf("reboot|%s", req.HostIP)
		result := global.RedisClient.Publish(context.Background(), channelName, channelMessge)
		if result.Err() != nil {
			fmt.Println("Failed to publish message:", result.Err())
			return response.ErrCreate.SetMsg(result.Err().Error())
		}
	}
	return response.OK
}

